<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"> <!-- 指定文档使用UTF-8字符编码 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- 设置视口，以适应不同设备屏幕大小 -->
    <title>Beating Heart</title> <!-- 文档标题 -->
    <style>
        /* 样式表定义 */
        body {
            background-color: black; /* 设置页面背景颜色为黑色 */
            margin: 0; /* 去除页面默认边距 */
            overflow: hidden; /* 隐藏超出画布的内容 */
        }
        canvas {
            display: block; /* 将画布作为块级元素显示 */
            margin: auto; /* 使画布在页面中居中 */
        }
        .text {
            position: absolute; /* 将文本绝对定位 */
            top: 50%; /* 使文本距离页面顶部50% */
            left: 50%; /* 使文本距离页面左侧50% */
            transform: translate(-50%, -50%); /* 将文本向左、向上平移自身宽度和高度的一半，实现在页面中居中 */
            color: #FF69B4; /* 设置文本颜色为浅粉色 */
            font-family: '宋体'; /* 设置文本字体为宋体 */
            font-size: 18px; /* 设置文本大小为18像素 */
            text-align: center; /* 使文本内容居中 */
        }
</style>
</head>
<body>
    <!-- 页面内容定义 -->
    <canvas id="heartCanvas" width="640" height="480"></canvas> <!-- 创建一个宽640像素、高480像素的画布，并设置其ID为heartCanvas -->
    <div class="text" style="top: 5%;">点燃我 温暖你</div> <!-- 创建一个文本元素，内容为“点燃我 温暖你”，并设置其样式类为text，距离页面顶部5% -->
    <script src="js/heart.js"></script> <!-- 引入heart.js脚本文件 -->
</body>
<script>
	// 定义画布的宽度和高度，以及画布的中心点坐标
	const CANVAS_WIDTH = 640;
	const CANVAS_HEIGHT = 480;
	const CANVAS_CENTER_X = CANVAS_WIDTH / 2;
	const CANVAS_CENTER_Y = CANVAS_HEIGHT / 2;
	
	// 定义图像的放大因子，用于调整爱心的大小
	const IMAGE_ENLARGE_FACTOR = 11;
	
	// 定义爱心的颜色
	const HEART_COLOR = "#FF69B4";
	
	// 生成爱心上的一个点的坐标
	function generateHeartCoordinate(t, shrinkRatio = IMAGE_ENLARGE_FACTOR) {
	  // 使用参数t计算原始的x和y坐标
	  let x = 16 * (Math.sin(t) ** 3);
	  let y = -(13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t));
	
	  // 根据缩放比例调整x和y坐标
	  x *= shrinkRatio;
	  y *= shrinkRatio;
	
	  // 将坐标转换到画布的中心
	  x += CANVAS_CENTER_X;
	  y += CANVAS_CENTER_Y;
	
	  // 返回调整后的坐标，向下取整以确保坐标为整数
	  return { x: Math.floor(x), y: Math.floor(y) };
	}
	
	// 绘制爱心的函数
	function drawHeart(context, ratio, frame) {
	  // 清空画布
	  context.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
	
	  // 绘制爱心的光晕部分
	  let heartHaloPoints = new Set();
	  for (let i = 0; i < 3000 + 4000 * Math.abs(customCurve(frame / 10 * Math.PI) ** 2); i++) {
	    // 生成一个随机的t值，用于计算坐标
	    let t = Math.random() * 4 * Math.PI;
	    // 使用generateHeartCoordinate函数计算坐标，并使用一个更大的缩放比例来使光晕更大
	    let { x, y } = generateHeartCoordinate(t, 11.5);
	    // 计算一个力的大小，用于调整光晕的扩散效果
	    let force = -1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.6);
	    // 根据力的大小调整x和y坐标
	    x -= ratio * force * (x - CANVAS_CENTER_X);
	    y -= ratio * force * (y - CANVAS_CENTER_Y);
	    // 添加一些随机的偏移量，使光晕更加自然
	    x += Math.floor(Math.random() * 29 - 14);
	    y += Math.floor(Math.random() * 29 - 14);
	    // 使用fillRect函数绘制一个2x2的正方形，作为光晕的一个点
	    context.fillStyle = HEART_COLOR;
	    context.fillRect(x, y, 2, 2);
	  }
	
	  // 绘制爱心的主体部分
	  let allPoints = []; // 存储所有点的数组
	  let originalPoints = new Set(); // 存储原始点的集合
	  let edgeDiffusionPoints = new Set(); // 存储边缘扩散点的集合
	  let centerDiffusionPoints = new Set(); // 存储中心扩散点的集合
	
	  // 生成原始点
	  for (let i = 0; i < 2000; i++) {
	    let t = Math.random() * 2 * Math.PI;
	    let { x, y } = generateHeartCoordinate(t);
	    originalPoints.add({ x, y });
	  }
	
	  // 从原始点生成边缘扩散点
	  originalPoints.forEach(({ x, y }) => {
	    for (let i = 0; i < 3; i++) {
	      let newX = x, newY = y;
	      newX += Math.random() * 5 - 2.5;
	      newY += Math.random() * 5 - 2.5;
	      edgeDiffusionPoints.add({ x: newX, y: newY });
	    }
	  });
	
	  // 生成中心扩散点
	  for (let i = 0; i < 6000; i++) {
	    let { x, y } = Array.from(originalPoints)[Math.floor(Math.random() * originalPoints.size)];
	    let newX = x, newY = y;
	    newX += Math.random() * 15 - 7.5;
	    newY += Math.random() * 15 - 7.5;
	    centerDiffusionPoints.add({ x: newX, y: newY });
	  }
	
	  // 根据力的大小调整所有点的坐标，并将它们添加到allPoints数组中
	  originalPoints.forEach(({ x, y }) => {
	    let newX = x, newY = y;
	    let force = 1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.52);
	    newX -= ratio * force * (x - CANVAS_CENTER_X);
	    newY -= ratio * force * (y - CANVAS_CENTER_Y);
	    allPoints.push({ x: Math.floor(newX), y: Math.floor(newY), size: Math.floor(Math.random() * 3 + 1) });
	  });
	
	  edgeDiffusionPoints.forEach(({ x, y }) => {
	    let newX = x, newY = y;
	    let force = 1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.52);
	    newX -= ratio * force * (x - CANVAS_CENTER_X);
	    newY -= ratio * force * (y - CANVAS_CENTER_Y);
	    allPoints.push({ x: Math.floor(newX), y: Math.floor(newY), size: Math.floor(Math.random() * 2 + 1) });
	  });
	
	  centerDiffusionPoints.forEach(({ x, y }) => {
	    let newX = x, newY = y;
	    let force = 1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.52);
	    newX -= ratio * force * (x - CANVAS_CENTER_X);
	    newY -= ratio * force * (y - CANVAS_CENTER_Y);
	    allPoints.push({ x: Math.floor(newX), y: Math.floor(newY), size: Math.floor(Math.random() * 2 + 1) });
	  });
	
	  // 绘制所有点
	  allPoints.forEach(({ x, y, size }) => {
	    context.fillStyle = HEART_COLOR;
	    context.fillRect(x, y, size, size);
	  });
	
	  // 添加文本 "stormsha" 到爱心中间
	  context.font = "bold 24px Arial";
	  context.fillStyle = HEART_COLOR;
	  context.textAlign = "center";
	  context.fillText("stormsha", CANVAS_CENTER_X, CANVAS_CENTER_Y);
	}
	
	// 定义一个自定义的曲线函数，用于调整爱心的跳动效果
	function customCurve(p) {
	  return 2 * (2 * Math.sin(4 * p)) / (2 * Math.PI);
	}
	
	// 当文档加载完成时，开始动画
	document.addEventListener("DOMContentLoaded", () => {
	  // 获取画布和2d上下文
	  const canvas = document.getElementById("heartCanvas");
	  const context = canvas.getContext("2d");
	
	  // 定义一些变量，用于控制动画
	  let ratio = 0; // 力的大小比例
	  let frame = 0; // 当前帧数
	
	  // 动画函数
	  function animate() {
	    // 根据当前帧数计算力的大小比例
	    ratio = 10 * customCurve(frame / 10 * Math.PI);
	    // 调用drawHeart函数绘制爱心
	    drawHeart(context, ratio, frame);
	    // 增加帧数
	    frame++;
	    // 请求下一帧的动画
	    requestAnimationFrame(animate);
	  }
	
	  // 开始动画
	  animate();
	});
</script>
</html>